import java.io.*;
import java.net.*;
import java.util.*;
import java.awt.*;

import javax.swing.*;

import org.json.JSONException;
import org.json.JSONObject;


public class DMserver extends JFrame
{

	private static int numPlayers;
	private static int playerTurn; //player whos turn it is
	private static ArrayList<HandleAClient> clients = new ArrayList<HandleAClient>();
	private ServerSocket serverSocket;
	private static JTextArea jta = new JTextArea();
	private JPanel buttonPanel = new ButtonPanel(this);
	private JPanel scenrioPanel = new ScenarioPanel(this);
	private JTextField input;
	
	public static void main(String[] args) throws IOException, JSONException
	{
		new DMserver(Integer.parseInt(args[0]));
		while(true)
		{
			
		}
		
	}
	
	public DMserver(int players)
	{	
		
		input = new JTextField();
		
		setLayout(new BorderLayout());
		add(new JScrollPane(jta), BorderLayout.CENTER);
		add(buttonPanel, BorderLayout.EAST);
		add(scenrioPanel,BorderLayout.WEST);
		add(input, BorderLayout.SOUTH);
		setTitle("DM server");
		setSize(650,300);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		
		try
		{
			this.serverSocket = new ServerSocket(8000);
			jta.append("DM sever started at " + new Date() + '\n');
			
			numPlayers = 0;
			playerTurn = 0;
			
			do 
			{
				newPlayer();
			}while(numPlayers < players);
		}
		
		catch(IOException ex)
		{
			System.err.println(ex);
		}
	}
	
	public String getInput()
	{
		return this.input.getText();
	}
	
	public void writeMessage(String message)
	{
		jta.append(message + "\n");
	}
	
	public void newPlayer() throws IOException
	{
		HandleAClient client;
		Socket socket = this.serverSocket.accept();
		jta.setEditable(false);
		jta.append("Starting Thread for client " + numPlayers + " at "+ new Date() + '\n');
		
		InetAddress inetAddress = socket.getInetAddress();
		jta.append("Player " + numPlayers + "'s host name is" + inetAddress.getHostName() + "\n");
		jta.append("Player " + numPlayers + "'s IP address is "+ inetAddress.getHostAddress() +  "\n");
		
		client = new HandleAClient(socket,numPlayers);
		clients.add(client);
		new Thread(client).start();
		clients.get(numPlayers).send("welcome player number " + numPlayers);
		this.numPlayers++;
	}
	/**
	 * removes a player who disconnected
	 * @param plindexayerNum
	 */
	public void removePlayer(int playerNum)
	{
		clients.set(playerNum, null);
		jta.append("removed player " + playerNum + " \n");
	}
	/**
	 * moves the turn to the next player
	 */
	public static void nextTurn() 
	{
		if (playerTurn == numPlayers-1) {playerTurn = 0;}
		else{playerTurn++;}
		System.out.println("turned passed to player:" + playerTurn + "/" + numPlayers);
		if (clients.get(playerTurn)==null)
		{
			System.out.println("player was blank");
			nextTurn();
		}
	}
	
	public static int getTurn()
	{return playerTurn;}
	
	public void sendAttack(int toHit, int damage, int target) throws JSONException, IOException
	{
		try
		{
			HandleAClient player = clients.get(target);
			player.sendAttack(toHit, damage);
		}
		catch(Exception e)
		{
			System.err.println("error in sending attack");
			
		}
	}
	
	public void sendDOTAttack(int toHit, int damage, int DOTdam, int DOTred, int target) throws JSONException, IOException
	{
		try
		{
			HandleAClient player = clients.get(target);
			player.sendDOTAttack(toHit, damage, DOTdam, DOTred);
		}
		catch(Exception e)
		{
			System.err.println("error in sending attack");
			
		}
	}
	
	/**
	 * sends the endTurn command to all players
	 * @throws IOException
	 */
	public void endTurn() throws IOException
	{
		for (HandleAClient player : clients)
		{
			if (player !=null){player.send("endTurn");}
		}
	}
	
	class HandleAClient implements Runnable
	{
		private Socket socket;
		private int playerNum;//player number on server
		
		public HandleAClient(Socket socket, int playerNum)
		{
			this.socket = socket;
			this.playerNum = playerNum;
		}
		

		public void run()
		{
			
			DataInputStream inputFromClient;
			DataOutputStream outputToClient;
			String message;
			String reply;
			Boolean connected= true;
			
			try
			{
				
				while(connected)
				{
					inputFromClient = new DataInputStream(socket.getInputStream());
					outputToClient = new DataOutputStream(socket.getOutputStream());

					message = "";
					reply = "";
				
					InputStreamReader inputReader = new InputStreamReader(inputFromClient);
					BufferedReader input = new BufferedReader(inputReader);
					PrintWriter output = new PrintWriter(outputToClient);
					message = input.readLine();
					
					jta.append("player said " + message + "\n");
					System.out.println("player " +  this.playerNum + " input= " + message);
					
					if (message==null)
					{
						DMserver.this.removePlayer(playerNum);
						connected=false;
					}
					
					if (DMserver.getTurn() == this.playerNum)
					{
						switch (message)
						{
				
						case "wait":
							reply = "turn passed to next player";
							DMserver.nextTurn();
							break;
						case "attack":
							message = input.readLine();
							JSONObject attackString = new JSONObject(message);
							System.out.println("attack=" + attackString);
							int toHit = attackString.getInt("toHit");
							int damage = attackString.getInt("damage");
							int target = attackString.getInt("target");
							DMserver.this.sendAttack(toHit, damage, target);
							break;
						default:
							reply = "you sent " + message;
							break;

						}
					}
					else
					{
						reply = "not your turn";
					}
					System.out.println("player " +  this.playerNum + " reply= "+reply);
					output.println(reply);
					output.flush();		
				}
			}
			catch(Exception e)
			{
				System.err.println(e);
				e.printStackTrace();
			}
		}
		
		public void sendAttack(int toHit, int damage) throws JSONException, IOException
		{
			JSONObject attackString = new JSONObject();
			
			DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
			PrintWriter output = new PrintWriter(outputToClient);
			attackString.put("toHit",toHit);
			attackString.put("damage", damage);
			jta.append("sent attack" + attackString + "\n");
			output.println("attack");
			output.flush();
			output.println(attackString);
			output.flush();
		}
		
		public void sendDOTAttack(int toHit, int damage, int DOTdam, int DOTred) throws JSONException, IOException
		{
			JSONObject attackString = new JSONObject();
			
			DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
			PrintWriter output = new PrintWriter(outputToClient);
			attackString.put("toHit",toHit);
			attackString.put("damage", damage);
			attackString.put("DOTdam", DOTdam);
			attackString.put("DOTred",DOTred);
			jta.append("sent attack" + attackString + "\n");
			output.println("attack");
			output.flush();
			output.println(attackString);
			output.flush();
		}
		
		public void send(String message) throws IOException
		{
			try
			{
				DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
				PrintWriter output = new PrintWriter(outputToClient);
				jta.append("sent " + message + " to player:" + playerNum + "\n");
				output.println(message);
				output.flush();
			}
			catch(IOException e)
			{
				System.err.println(e);
				e.printStackTrace();
			}
		}
	}

}


